iT邦幫忙

2024 iThome 鐵人賽

DAY 2
0

本次學習目標是

  1. 建立 Quarkus 專案
  2. 建置 Kubernetes YAML,認識 Deployment 和 Service 資源
  3. 使用 Jib 建置容器 image

建立 Quarkus 專案

建立 Quarkus 專案可以使用 Maven 或是 Gradle 等專案自動工具建置。此範例將使用 Gradle,而現行的 IDE 都相當方便直接用勾選方式即可建置一個專案,或是至 Quarkus 官方也可以建置。

主要需要的相依套件有以下

dependencies {
    implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")
    implementation enforcedPlatform("${quarkusPlatformGroupId}:quarkus-camel-bom:${quarkusPlatformVersion}")
    implementation 'org.apache.camel.quarkus:camel-quarkus-log'
    implementation 'org.apache.camel.quarkus:camel-quarkus-core'
    implementation 'org.apache.camel.quarkus:camel-quarkus-microprofile-health'
    implementation 'org.apache.camel.quarkus:camel-quarkus-kubernetes'
    implementation 'io.quarkus:quarkus-config-yaml'
    implementation 'io.quarkus:quarkus-resteasy-jackson'
    implementation 'org.apache.camel.quarkus:camel-quarkus-micrometer'
    implementation 'io.quarkus:quarkus-smallrye-health'
    implementation 'io.quarkus:quarkus-container-image-jib'
    implementation 'io.quarkus:quarkus-kubernetes'
    implementation 'io.quarkus:quarkus-micrometer'
    implementation 'io.quarkus:quarkus-arc'
    implementation 'io.quarkus:quarkus-resteasy'
    testImplementation 'io.quarkus:quarkus-junit5'
    testImplementation 'io.rest-assured:rest-assured'
}

本次會注重於 quarkus-container-image-jibquarkus-kubernetes。首先介紹一下 Jib,用來為 Java 應用程式快速且簡易建立 Docker 或 OCI 容器 Image。相比傳統 Dockerfile 方式,Jib 提供了一種更直觀、更自動化的方式來整合 Java 應用程式並打包成容器 Image。

Jib 優勢可帶來

  1. 增加開發效率,不必特別管理 Dockerfile,加快了開發週期
  2. Image 品質,產生的 Image 更小、更快速、更安全
  3. 整合方面可以輕鬆整合到現有的 Maven 或 Gradle 建構框架流程中
  4. Daemonless,減少對 CLI 的依賴,不需要撰寫 Dockerfile 和呼叫 docker build/push。

再來是, quarkus-kubernetes 套件。Quarkus 使用 dekorate 透過框架安全預設值和使用者提供的配置自動產生 Kubernetes YAML 資源。其支援 Kubernetes、OpenShift 和 Knative 來產生對應的 YAML 資源。前面產生了 YAML 清單,當然可部署到目標 Kubernetes,透過 Kubernetes API 來實現。

透過 Jib 建構 Image 再透過 quarkus-kubernetes 來產生 YAML 清單,這樣可以在地端輕鬆的快速驗證內容。

前面大致說明了重點套件。接下來來實作吧! 理論上建置完 Quarkus 專案後會產生一個範例 API

@Path("/hello")
public class GreetingResource {

    @Inject
    GreetingConfig greetingConfig;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "Hello RESTEasy %s".formatted(greetingConfig.message());
    }
}

建置 Kubernetes YAML

對於 quarkus-kubernetes 套件配置以下,讓 Quarkus 被建構時,將 Kubernetes YAML 儲存至 kubernetes 目錄,這在 CI 時非常有用。

kubernetes:
  output-directory: kubernetes

再來透過 gradle: build 編譯專案,這時在 kubernetes 目錄可以發現一個 yml 和 json 檔案,原則上部署都是用 yml,除非想透過 API 方式,那就可以使用 json。裡面內容是預設框架給的 kubernetes 資源 YAML 清單。

$ tree kubernetes/
kubernetes/
├── kubernetes.json
└── kubernetes.yml

其資源分別是 ServiceDeployment 資源。

---
apiVersion: v1
kind: Service
metadata:
  annotations:
    app.quarkus.io/quarkus-version: 3.13.3
    app.quarkus.io/commit-id: 0ea6717ad4a8c436ab47cdffc6e1786e21aeb608
    app.quarkus.io/vcs-uri: https://gitlab.devpack.cc/Itachi_Chen/quarkus-sandbox.git
    app.quarkus.io/build-timestamp: 2024-08-23 - 18:57:59 +0000
  labels:
    app.kubernetes.io/name: ithome2024lab
    app.kubernetes.io/version: 1.0.0-SNAPSHOT
    app.kubernetes.io/managed-by: quarkus
  name: ithome2024lab
spec:
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: 8080
  selector:
    app.kubernetes.io/name: ithome2024lab
    app.kubernetes.io/version: 1.0.0-SNAPSHOT
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    app.quarkus.io/quarkus-version: 3.13.3
    app.quarkus.io/commit-id: 0ea6717ad4a8c436ab47cdffc6e1786e21aeb608
    app.quarkus.io/vcs-uri: https://gitlab.devpack.cc/Itachi_Chen/quarkus-sandbox.git
    app.quarkus.io/build-timestamp: 2024-08-23 - 18:57:59 +0000
  labels:
    app.kubernetes.io/name: ithome2024lab
    app.kubernetes.io/version: 1.0.0-SNAPSHOT
    app.kubernetes.io/managed-by: quarkus
  name: ithome2024lab
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/version: 1.0.0-SNAPSHOT
      app.kubernetes.io/name: ithome2024lab
  template:
    metadata:
      annotations:
        app.quarkus.io/quarkus-version: 3.13.3
        app.quarkus.io/commit-id: 0ea6717ad4a8c436ab47cdffc6e1786e21aeb608
        app.quarkus.io/vcs-uri: https://gitlab.devpack.cc/Itachi_Chen/quarkus-sandbox.git
        app.quarkus.io/build-timestamp: 2024-08-23 - 18:57:59 +0000
      labels:
        app.kubernetes.io/managed-by: quarkus
        app.kubernetes.io/version: 1.0.0-SNAPSHOT
        app.kubernetes.io/name: ithome2024lab
    spec:
      containers:
        - env:
            - name: KUBERNETES_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          image: registry.hub.docker.com/cch0124/ithome2024lab:1.0.0-SNAPSHOT
          imagePullPolicy: Always
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /q/health/live
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 5
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          name: ithome2024lab
          ports:
            - containerPort: 8080
              name: http
              protocol: TCP
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /q/health/ready
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 5
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          startupProbe:
            failureThreshold: 3
            httpGet:
              path: /q/health/started
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 5
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10

從結果來看其實 DeploymentService在地端驗證配置已經很足夠了。如果要上到 DEV、QAS 等環境則需要再配置一些資源,例如 resourceIngress 等資源。

認識 Deployment 和 Service 資源

Deployment 是 Kubernetes 中用於管理 ReplicaSet 的資源,而 ReplicaSet 用於管理 Pod 的副本數量。基本上 Deployment 有以下特性

  • 副本管理,可以指定希望運行多少個 Pod 副本,且會自動維護這個數量。當 Pod 突然故障或被刪除,Deployment 會自動創建新的 Pod 來替換
  • 滾動更新,Deployment 預設是執行滾動更新,即逐個替換舊 Pod 為新 Pod,保證服務在更新過程中保持可用性
  • 回滾,如果新的 Deployment 版本出現問題,可以回滾到之前的版本
  • 縮放 Pod 副本,當資源到達一定程度時可透過放大 Pod 數量來分配流量,以提高系統穩定性和可用性

順帶提一下,ReplicaSet 不支持滾動更新、回滾等高級功能。因此實務上會使用 Deployment 資源。而 Deployment 在做回滾時則需要 ReplicaSet 的存在,因為 Deployment 在作異動時就是新增一個新 ReplicaSet 和保留舊 ReplicaSet

下面為資源之間關係

Deployment -----> ReplicaSet -----> Pod

Service,透過 Endpoints 定義了一組 Pod 的邏輯集合,並提供一個穩定的網路端點(IP 和 Port)來存取這些 Pod。其主要特性有以下

  • 服務發現,透過 Label Selector 選擇一系列 Pod,並將這些 Pod 暴露為一個服務
  • 負載均衡,將請求均勻分發到後端的 Pod 上,實現負載均衡
  • 服務抽象,提供了一個穩定的網路端點,即使後端的 Pod IP 發生變化,Service 資源的 IP 地址也不會改變

下面為資源之間關係

Service -----> Endpoints -----> Pod

使用 Jib 建置容器 image

接著在 application.yaml 配置 Jib 內容,如下

quarkus:
  container-image:
    group: cch0124
    name: ${quarkus.application.name:unset}
    tag: ${quarkus.application.version:latest}
    builder: jib
    labels:
      "maintainer": cch
      "app": ${quarkus.application.name}
    registry: registry.hub.docker.com
  jib:
    base-native-image: quay.io/quarkus/quarkus-micro-image:2.0
    user: itachi
    working-directory: /home/jboss
    platforms: linux/amd64

配置完後,嘗試建置 Image,如下指令並搭配變數來進行彈性的配置。相對應參數可以參閱官方

gradle build -Dquarkus.package.type=native -Dquarkus.native.container-build=true -Dquarkus.kubernetes.deploy=false  -Dquarkus.container-image.push=true  -Dquarkus.container-image.build=true -Dquarkus.container-image.additional-tags="$(git log -1 --pretty=format:%h),day02"  -Dquarkus.container-image.username=${USER} -Dquarkus.container-image.password=${PASSWORD} -Dquarkus.kubernetes.version=$(git log -1 --pretty=format:%h)

執行後 Jib 建置了 Image 也將 Image 推到 docker hub 上,當中 tag 會有當下的 commit sha、day02 以及 1.0.0-SNAPSHOT。

https://ithelp.ithome.com.tw/upload/images/20240824/20104688Ye61WR8HXp.png


上一篇
使用 Quarkus AKA Argo CD 整合 Kubernetes
下一篇
地端部署 Quarkus 專案至 Kubernetes 環境
系列文
當 Quarkus 想要騎乘駱駝並用8腳章魚掌控舵手 31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言